/*
 * PaqueteClass.java	
 *
 * Copyright 2011 Universidad Francisco de Paula Santander (UFPS).
 * Todos los Derechos Reservados.
 * Creado el 07/10/11, 1o:50:38 PM
 */
package com.ufps.cuatro.modelo.codificacion;

import com.ufps.cuatro.util.base.ObjectBase;
import java.util.ArrayList;

/**
 * <i><b>PaqueteClass:</b></i><p>Esta Clase Representa el Paquete al cual será vinculada
 * el <code>Componente</code>.</p>
 * 
 * @author Carlos A. Torres C. - Dolly E. Guerrero. <https://code.google.com/p/tesis4dor/>
 * @version 1.0 07/10/11
 * @see ObjectBase
 */
public class PaqueteClass extends ObjectBase{
    private static final long serialVersionUID = -924225367166701089L;
    
    private String strNombre;
    private boolean root;
    private ArrayList<PaqueteClass> objHijos;
    private PaqueteClass objRoot;
    
    /**
     * Identificador de Paquete.
     */
    public static int autoID; 
    
    static{
        autoID = 0;
    }
    
    /**
     * Constructor que inicializa los Parametros.
     * @param strNombre Nombre del Paquete.
     * @param objRoot  Paquete Padre.
     */
    public PaqueteClass(String strNombre, PaqueteClass objRoot) {
        this.strNombre = strNombre;
        this.objRoot = objRoot;
        this.root = false;
        this.objHijos = new ArrayList<PaqueteClass>();
        id = autoID++;
    }

    /**
     * Constructor que inicializa los Parametros.
     * @param strNombre Nombre del Paquete.
     */
    public PaqueteClass(String strNombre) {
        this.strNombre = strNombre;
        this.objRoot = null;
        this.root = true;
        this.objHijos = new ArrayList<PaqueteClass>();
        id = autoID++;
    }

    /**
     * Devuelve la Colección de Paquetes hijos.
     * @return Colección de Paquetes hijos.
     */
    public ArrayList<PaqueteClass> getObjHijos() {
        try{
            return objHijos;
        }catch(java.lang.NullPointerException ex){}
        return null;
    }

    /**
     * Establece la Colección de Paquetes hijos.
     * @param objHijos Colección de Paquetes hijos.
     */
    public void setObjHijos(ArrayList<PaqueteClass> objHijos) {
        this.objHijos = objHijos;
    }

    /**
     * Devuelve el estado que determina si es el Paquete Padre.
     * @return Estado que determina si es el Paquete Padre.
     */
    public boolean isRoot() {
        return root;
    }

    /**
     * Establece el estado que determina si es el Paquete Padre.
     * @param root Estado que determina si es el Paquete Padre.
     */
    public void setRoot(boolean root) {
        this.root = root;
    }

    /**
     * Deveulve el Nombre del Paquete.
     * @return Nombre del Paquete.
     */
    public String getStrNombre() {
        return strNombre;
    }

    /**
     * Establece el Nombre del Paquete.
     * @param strNombre Nombre del Paquete.
     */
    public void setStrNombre(String strNombre) {
        this.strNombre = strNombre;
    }
    
    /**
     * Devuelve la Colección de los Nombres de todos los Paquetes que representan
     * la estructura actual del Paquete.
     * @return Colección de los Nombres de todos los Paquetes que representan
     * la estructura actual del Paquete.
     */
    public ArrayList<String> getPathString(){
        ArrayList<String> objPath = new ArrayList<String>();        
        getPathString(objPath);
        return objPath;
    }
    
    /**
     * Devuelve Colección de los Nombres de todos los Paquetes que representan
     * la estructura actual del Paquete Padre Recibo.
     * @param objPathParent Colección que almacenará los Nombres de los Paquetes.
     * @param objPaqueteParent Paquete Padre desde el cual se generará la Colección.
     * @param objPaqueteHijo Paquete Actual.
     */
    public void getPathString(ArrayList<String> objPathParent, PaqueteClass objPaqueteParent, PaqueteClass objPaqueteHijo){        
       try{
            objPathParent.add(objPaqueteParent.strNombre + "." + objPaqueteHijo.strNombre);
            for(PaqueteClass objPaquete : objPaqueteHijo.objHijos){
                getPathString(objPathParent, objPaqueteHijo, objPaquete);
            }        
        }catch(java.lang.NullPointerException ex){}
       
    }  
    
    /**
     * Devuelve Colección de los Nombres de todos los Paquetes que representan
     * la estructura actual del Paquete Padre Recibo.
     * @param objPathParent Colección que almacenará los Nombres de los Paquetes.
     * @param objPaqueteParent Paquete Padre desde el cual se generará la Colección.
     */
    public void getPathString(ArrayList<String> objPathParent, PaqueteClass objPaqueteParent){        
        try{
            objPathParent.add(objPaqueteParent.getCanonicalPath());
            for(PaqueteClass objPaqueteHijo : objPaqueteParent.objHijos){
                getPathString(objPathParent, objPaqueteHijo);
            }        
        }catch(java.lang.NullPointerException ex){}
        
    }
    
    /**
     * Devuelve la Colección de los Nombres de todos los Paquetes que representan
     * la estructura actual del Paquete en el Parametro Recibido.
     * @param objPathParent Colección de los Nombres de todos los Paquetes que representan
     * la estructura actual del Paquete.
     */
    public void getPathString(ArrayList<String> objPathParent){        
        try{
            objPathParent.add(getCanonicalPath());
            for(PaqueteClass objPaqueteHijo : objHijos){
                getPathString(objPathParent, objPaqueteHijo);
            }        
        }catch(java.lang.NullPointerException ex){}
    
    }
    
    /**
     * Devuelve el Nombre Canónico del Paquete.
     * @return Nombre Canónico del Paquete.
     */
    public String getCanonicalPath(){
        if(this.root){
            return this.strNombre;
        }
        return this.objRoot.getCanonicalPath() + "." + strNombre;
    }
    
    
    @Override
    public String toString(){
       return strNombre;
    }
    
    /**
     * Agrega un Paquete a la Colección actual de Paquetes Hijos.
     * @param objPaquete Nuevo Paquete.
     * @return boolean que determina el Estado de la Inclusión del nuevo Paquete.
     */
    public boolean addHijo(PaqueteClass objPaquete){
        try{
            String strPaquete = "";
            for(PaqueteClass objPaqueteHijo : this.objHijos){
                strPaquete = objPaqueteHijo.getStrNombre();
                if(strPaquete.equals(objPaquete.getStrNombre())){
                    return false;
                }
            }
            objPaquete.objRoot = this;
            return this.objHijos.add(objPaquete);
        }catch(java.lang.NullPointerException ex){}
        return false;
    }
    
    /**
     * Reemplaza la Referecnia de un PAquete Recibido en los Parametros.
     * @param objPaqueteOld Referencia del Paquete de la Colección.
     * @param objPaqueteNew Referencia del Nuevo Paquete.
     * @return Referencia que determina el estado del reemplazo.
     */
    public PaqueteClass editHijo(PaqueteClass objPaqueteOld, PaqueteClass objPaqueteNew){
        int idTemp = objHijos.indexOf(objPaqueteOld);
        if(idTemp > -1){
            for(PaqueteClass objPaqueteHijo : this.objHijos){
                String strPaquete = objPaqueteHijo.getStrNombre();
                if(strPaquete.equals(objPaqueteNew.getStrNombre())){
                    return null;
                }
            }
            return objHijos.set(idTemp, objPaqueteNew);
        }
        return null;
    }    
    
    /**
     * Elimina el Paquete recibido en el Parametro de la Colección de Psquetes
     * Hijos.
     * @param objPaquete Paquete que se eliminará.
     * @return boolean que determina el estado de la eliminación.
     */
    public boolean delHijo(PaqueteClass objPaquete){
        return this.objHijos.remove(objPaquete);
    }    
    
    /**
     * Busca y devuelve el Paquete identificado con el Parametro recibido.
     * @param strPaquete Nombre del Paquete que se Buscara en la Colección de 
     * Paquetes Hijos o null si no se encuentra.
     * @return Referencia que representa el resultado de la busqueda.
     */
    public PaqueteClass getHijo(String strPaquete){
        for(PaqueteClass objPaquete : objHijos){
            if(objPaquete.strNombre.equals(strPaquete)){
                return objPaquete;
            }            
        }
        return null;
    }

    /**
     * Devuelve la Referencia del Paquete Padre del Paquete Actual o null si es
     * la raíz.
     * @return Referencia del Paquete Padre del Paquete Actual o null si es
     * la raíz.
     */
    public PaqueteClass getObjRoot() {
        return objRoot;
    }

    /**
     * Establece la Referencia del Paquete Padre del Paquete Actual o null si es
     * la raíz.
     * @param objRoot Referencia del Paquete Padre del Paquete Actual o null si es
     * la raíz.
     */
    public void setObjRoot(PaqueteClass objRoot) {
        this.objRoot = objRoot;
    }  

    @Override
    public Object clone() {
        PaqueteClass objClon = null;
        //Primero se Clona la Referencia Local
        objClon = (PaqueteClass) super.clone();
        //Ahora se hace la Clonación Profunda
        if(this.strNombre != null){
            ((PaqueteClass)objClon).setStrNombre(new String(strNombre.toCharArray()));
        }
        if(this.objHijos != null){
            if(!this.objHijos.isEmpty()){
                ((PaqueteClass)objClon).setObjHijos((ArrayList<PaqueteClass>) objHijos.clone());
            }
        }
        return objClon;
    }
}
